home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / jpeg.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-14  |  5.8 KB  |  207 lines

  1. /* jpeg.c - load JPEG image from file
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 1997 Alfredo K. Kojima
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24.  
  25.  
  26.  
  27.  
  28. #ifdef USE_JPEG
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33.  
  34. #include <jpeglib.h>
  35.  
  36. #include "wraster.h"
  37.  
  38. /*
  39.  * <setjmp.h> is used for the optional error recovery mechanism shown in
  40.  * the second part of the example.
  41.  */
  42.  
  43. #include <setjmp.h>
  44.  
  45. /*
  46.  * ERROR HANDLING:
  47.  *
  48.  * The JPEG library's standard error handler (jerror.c) is divided into
  49.  * several "methods" which you can override individually.  This lets you
  50.  * adjust the behavior without duplicating a lot of code, which you might
  51.  * have to update with each future release.
  52.  *
  53.  * Our example here shows how to override the "error_exit" method so that
  54.  * control is returned to the library's caller when a fatal error occurs,
  55.  * rather than calling exit() as the standard error_exit method does.
  56.  *
  57.  * We use C's setjmp/longjmp facility to return control.  This means that the
  58.  * routine which calls the JPEG library must first execute a setjmp() call to
  59.  * establish the return point.  We want the replacement error_exit to do a
  60.  * longjmp().  But we need to make the setjmp buffer accessible to the
  61.  * error_exit routine.  To do this, we make a private extension of the
  62.  * standard JPEG error handler object.  (If we were using C++, we'd say we
  63.  * were making a subclass of the regular error handler.)
  64.  *
  65.  * Here's the extended error handler struct:
  66.  */
  67.  
  68. struct my_error_mgr {
  69.   struct jpeg_error_mgr pub;    /* "public" fields */
  70.  
  71.   jmp_buf setjmp_buffer;    /* for return to caller */
  72. };
  73.  
  74. typedef struct my_error_mgr * my_error_ptr;
  75.  
  76. /*
  77.  * Here's the routine that will replace the standard error_exit method:
  78.  */
  79.  
  80. static void
  81. my_error_exit(j_common_ptr cinfo)
  82. {
  83.   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  84.   my_error_ptr myerr = (my_error_ptr) cinfo->err;
  85.  
  86.   /* Always display the message. */
  87.   /* We could postpone this until after returning, if we chose. */
  88.   (*cinfo->err->output_message) (cinfo);
  89.  
  90.   /* Return control to the setjmp point */
  91.   longjmp(myerr->setjmp_buffer, 1);
  92. }
  93.  
  94.  
  95. RImage*
  96. RLoadJPEG(RContext *context, char *file_name, int index)
  97. {
  98.     RImage *image = NULL;
  99.     struct jpeg_decompress_struct cinfo;
  100.     int i;
  101.     unsigned char *ptr;
  102.     JSAMPROW buffer[1], bptr;
  103.     FILE *file;
  104.     /* We use our private extension JPEG error handler.
  105.      * Note that this struct must live as long as the main JPEG parameter
  106.      * struct, to avoid dangling-pointer problems.
  107.      */
  108.     struct my_error_mgr jerr;
  109.  
  110.     file = fopen(file_name, "r");
  111.     if (!file) {
  112.     RErrorCode = RERR_OPEN;
  113.     return NULL;
  114.     }
  115.  
  116.     cinfo.err = jpeg_std_error(&jerr.pub);
  117.     jerr.pub.error_exit = my_error_exit;
  118.     /* Establish the setjmp return context for my_error_exit to use. */
  119.     if (setjmp(jerr.setjmp_buffer)) {
  120.        /* If we get here, the JPEG code has signaled an error.
  121.     * We need to clean up the JPEG object, close the input file, and return.
  122.     */
  123.        jpeg_destroy_decompress(&cinfo);
  124.        fclose(file);
  125.        return NULL;
  126.     }
  127.  
  128.     jpeg_create_decompress(&cinfo);
  129.  
  130.     jpeg_stdio_src(&cinfo, file);
  131.   
  132.     jpeg_read_header(&cinfo, TRUE);
  133.  
  134.     bptr = buffer[0] = (JSAMPROW)malloc(cinfo.image_width*cinfo.num_components);
  135.     if (!buffer[0]) {
  136.     RErrorCode = RERR_NOMEMORY;
  137.     goto bye;
  138.     }
  139.  
  140.     if(cinfo.jpeg_color_space==JCS_GRAYSCALE) {
  141.        cinfo.out_color_space=JCS_GRAYSCALE;
  142.     } else
  143.         cinfo.out_color_space = JCS_RGB;
  144.     cinfo.quantize_colors = FALSE;
  145.     cinfo.do_fancy_upsampling = FALSE;
  146.     cinfo.do_block_smoothing = FALSE;
  147.     jpeg_calc_output_dimensions(&cinfo);
  148.  
  149.     if (context->flags.optimize_for_speed)
  150.     image = RCreateImage(cinfo.image_width, cinfo.image_height, True);
  151.     else
  152.     image = RCreateImage(cinfo.image_width, cinfo.image_height, False);
  153.  
  154.     if (!image) {
  155.        RErrorCode = RERR_NOMEMORY;
  156.        goto bye;
  157.     }
  158.     jpeg_start_decompress(&cinfo);
  159.  
  160.     ptr = image->data;
  161.  
  162.     
  163.     if (cinfo.out_color_space==JCS_RGB) {
  164.     if (context->flags.optimize_for_speed) {
  165.         while (cinfo.output_scanline < cinfo.output_height) {
  166.         jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
  167.         bptr = buffer[0];
  168.         for (i=0; i<cinfo.image_width; i++) {
  169.             *ptr++ = *bptr++;
  170.             *ptr++ = *bptr++;
  171.             *ptr++ = *bptr++;
  172.             ptr++; /* skip alpha channel */
  173.         }
  174.         }
  175.     } else {
  176.         while (cinfo.output_scanline < cinfo.output_height) {
  177.         jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
  178.         bptr = buffer[0];
  179.         memcpy(ptr, bptr, cinfo.image_width*3);
  180.         ptr += cinfo.image_width*3;
  181.         }
  182.     }
  183.     } else {
  184.     while (cinfo.output_scanline < cinfo.output_height) {
  185.         jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
  186.         bptr = buffer[0];
  187.         for (i=0; i<cinfo.image_width; i++) {
  188.         *ptr++ = *ptr++ = *ptr++ = *bptr++;
  189.         }
  190.     }
  191.     }
  192.  
  193.     jpeg_finish_decompress(&cinfo);
  194.  
  195.   bye:
  196.     jpeg_destroy_decompress(&cinfo);
  197.  
  198.     fclose(file);
  199.  
  200.     if (buffer[0])
  201.     free(buffer[0]);  
  202.  
  203.     return image;
  204. }
  205.  
  206. #endif /* USE_JPEG */
  207.